home *** CD-ROM | disk | FTP | other *** search
/ CGI How-To / CGI HOW-TO.iso / chap7 / 7_3 / ht73.c next >
Encoding:
C/C++ Source or Header  |  1996-06-15  |  6.2 KB  |  250 lines

  1. /* Compile with:
  2.  *     cc string.o array.o dict.o cgilib.o ht73.c -o ht73 -lsdbm
  3.  */
  4.  
  5. #include <sdbm.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <fcntl.h>
  9. #include <string.h>
  10.  
  11. #include "cgilib.h"
  12.  
  13. #define DOMAINSIZE 30  /* Maximum size of domain name stored */
  14.  
  15. /*
  16.  * This structure is used to contain a movie's review information
  17.  * withing the dbm database.  The movie's name is not stored in
  18.  * this structure because it is contained in the records key.
  19.  */ 
  20. typedef struct
  21. {
  22.     int  lastVote;             /* the last vote: 1 to 10       */
  23.     int  votes[10];            /* votes[i] is # of votes of i  */
  24.     char lastVoter[DOMAINSIZE];/* domain name of the last voter*/
  25. } REVIEW;
  26.  
  27. /*
  28.  * This structure is a node of a binary tree of movie names.
  29.  */
  30. typedef struct _movienode
  31. {
  32.     char *movie;                /* The movie's title         */
  33.     struct _movienode *lt, *gt; /* Pointers to children      */
  34. } MOVIENODE;
  35.  
  36.  
  37. DBM *db;
  38.  
  39. /*
  40.  * Insert a movie title into the binary tree
  41.  */
  42. void insertMovie(char *movie, MOVIENODE **root)
  43. {
  44.     /* Insert a new node if we are at the bottom of the tree */
  45.     if (!*root)
  46.     {
  47.         *root          = malloc(sizeof(MOVIENODE));
  48.         (*root)->movie = movie;
  49.         (*root)->lt    = (*root)->gt = NULL;
  50.     }
  51.     /* Else traverse farther down the tree */
  52.     else
  53.     {
  54.         insertMovie(movie, strcasecmp((*root)->movie,movie) < 0
  55.         ? &(*root)->gt
  56.         : &(*root)->lt);
  57.     }
  58.    
  59. }
  60.  
  61.  
  62. /* 
  63.  * Perform an in-order traversal of the binary tree of movies
  64.  */
  65. void traverseMovies(MOVIENODE *root)
  66. {
  67.     /* Don't do anything to an empty tree */
  68.     if (!root) return;
  69.    
  70.     traverseMovies(root->lt);
  71.     htmlMovie(root->movie);
  72.     traverseMovies(root->gt);
  73.  
  74.     /* Free the dynamic memory associated with this node */
  75.     free(root->movie);
  76.     free(root);
  77. }
  78.  
  79.  
  80. htmlMovie(char *movie)
  81. {
  82.     datum   key, value;
  83.     REVIEW *rev;
  84.     int     votes = 0;
  85.     int     sum   = 0; 
  86.     int     i;
  87.  
  88.     /* Convert the character string into a datum structure */
  89.     key.dptr  = movie;
  90.     key.dsize = strlen(movie);
  91.  
  92.     value = sdbm_fetch(db,key);
  93.     rev   = (REVIEW *) value.dptr;
  94.  
  95.     for ( i = 0 ; i < 10 ; i++ )
  96.     {
  97.         sum   += rev->votes[i]*(i+1);
  98.         votes += rev->votes[i];
  99.     }
  100.  
  101.     /*
  102.      * Display information about this movie
  103.      */
  104.     printf("<H2>%s</H2><BLOCKQUOTE>", movie);
  105.     printf("<B>Average: %2.2f", (float)sum/(float)votes);
  106.     printf(" Votes: %d</B><BR>\n", votes);
  107.     printf("<IMG SRC=\"ht72a.cgi?score=");
  108.    
  109.     for( i=0 ; i < 9 ; i++ )
  110.     {
  111.         printf("%d+",rev->votes[i]);
  112.     }
  113.    
  114.     printf("%d",rev->votes[9]);
  115.    
  116.     printf("\" ALT=\"");
  117.     for( i=0 ; i < 10 ; i++ )
  118.     {
  119.         printf("%d:%d ",i+1,rev->votes[i]);
  120.     }
  121.    
  122.     printf("\"><BR>\n");
  123.     printf("Last vote from <B>%s</B> who gave ", rev->lastVoter);
  124.     printf("%s a %d out of 10.\n", movie, rev->lastVote);
  125.  
  126.     /*
  127.      * Build the Form for voting for this movie 
  128.      */
  129.     printf("<FORM ACTION=\"%s\">", getenv("SCRIPT_NAME"));
  130.     printf("<INPUT TYPE=\"hidden\" NAME=\"movie\" value=\"%s\">",
  131.        movie); 
  132.     printf("<SELECT NAME=\"score\">");
  133.     for ( i = 1 ; i <= 10 ; i++ )
  134.     {
  135.         printf("<OPTION> %d",i);
  136.     }
  137.     printf("</SELECT><INPUT TYPE=\"submit\" value=\"Vote\">");
  138.     printf("</FORM></BLOCKQUOTE><BR>\n");
  139. }
  140.  
  141.  
  142. void main()
  143. {
  144.     Dictionary dataDict = readParse();
  145.     datum      key;
  146.     MOVIENODE *root = NULL;
  147.     char      *tmp;
  148.     int        i;
  149.     int        score = dict_isKey(dataDict,"score")
  150.                    ? atoi(dict_valueForKey(dataDict,"score"))
  151.                    : 0;
  152.     char       *movie = dict_isKey(dataDict,"movie")
  153.                    ? dict_valueForKey(dataDict,"movie")
  154.                    : NULL;
  155.     
  156.     /* Output the HTML content type and header */ 
  157.     printf("Content-type: text/html\n\n");
  158.     printf("<HTML><HEAD><TITLE>Waite Movie Reviews</TITLE>");
  159.     printf("</HEAD><BODY>");
  160.     printf("<H1>Welcome to Waite Movie Reviews</H1><HR>");
  161.    
  162.     /*
  163.      * If a vote is being registered
  164.      */
  165.     if ( movie && score >=1 && score <= 10 && strchr(movie,'<') == NULL)
  166.     {
  167.         datum  value;
  168.         REVIEW *rev_ptr;
  169.         REVIEW rev;
  170.     
  171.         key.dptr  = movie;
  172.         key.dsize = strlen(movie);
  173.        
  174.         if (! (db = sdbm_open("movies", O_RDWR | O_CREAT, 0660)))
  175.         exit(1); 
  176.        
  177.         printf("Your vote of %d out of 10 for ", score);
  178.         printf("<B>%s</B> has been recorded.<HR>\n",movie);
  179.       
  180.         value = sdbm_fetch(db,key);
  181.        
  182.         /* If this is the first vote for a new movie
  183.      * Then we must initialize a new REVIEW structure
  184.      * so that all of the votes have an initial value of 0
  185.      */
  186.         if ( ! value.dptr )
  187.     {
  188.         int i;
  189.         
  190.         for ( i=0 ; i<10 ; i++ )
  191.         {
  192.             rev.votes[i] = 0;
  193.         }
  194.         value.dptr  = (char *) &rev;
  195.         value.dsize = sizeof(REVIEW);
  196.     }
  197.        
  198.         rev_ptr = (REVIEW *) value.dptr;
  199.         strncpy(rev_ptr->lastVoter,
  200.         getenv("REMOTE_HOST"),DOMAINSIZE);
  201.         rev_ptr->lastVote = score;
  202.         (rev_ptr->votes[score-1])++;
  203.         sdbm_store(db,key,value,DBM_REPLACE);
  204.         sdbm_close(db);
  205.     }
  206.    
  207.     if (! (db = sdbm_open("movies", O_RDONLY | O_CREAT, 0660)))
  208.         exit(1); 
  209.     
  210.     for ( key = sdbm_firstkey(db) ;
  211.       key.dptr != NULL        ;
  212.       key = sdbm_nextkey(db)  )
  213.     {
  214.         /*
  215.          * Allocate memory for the movie's title.
  216.      * Allocate an extra byte to null terminate the string.
  217.          */
  218.         tmp = malloc(key.dsize+1);
  219.        
  220.         /* Copy the movie's title into tmp */
  221.         bcopy(key.dptr,tmp,key.dsize);
  222.         tmp[key.dsize] = '\0';
  223.       
  224.         /* Insert the movie's title into the binary tree */
  225.         insertMovie(tmp,&root);
  226.     }
  227.     
  228.     /*
  229.      * Traverse the binary tree outputing each records 
  230.      * record and form in HTML format.
  231.      */
  232.     traverseMovies(root);
  233.  
  234.     /* Build the Form for voting for 'Other' */
  235.     printf("<H2>Other</H2><BLOCKQUOTE>");
  236.     printf("<FORM ACTION=\"%s\">", getenv("SCRIPT_NAME"));
  237.     printf("<INPUT NAME=\"movie\">");
  238.     printf("<SELECT NAME=\"score\">");
  239.     for ( i = 1 ; i <= 10 ; i++ )
  240.     {
  241.         printf("<OPTION> %d",i);
  242.     }
  243.     printf("</SELECT><INPUT TYPE=\"submit\" value=\"Vote\">");
  244.     printf("</FORM></BLOCKQUOTE><BR>\n");
  245.     printf("<HR></BODY></HTML>");
  246.    
  247.     sdbm_close(db);
  248. }
  249.  
  250.